Skip to main content

使用 Winston 实现分级日志收集

https://github.com/winstonjs/winston

日志库的必要性

  • 传输通道
    • Console 文件
    • File 文件
    • Http 通过http传输
    • Stream 流传输
  • 格式化
    • 时间戳
    • 格式美化
  • 日志分割
    • 按文件大小分割
    • 按写入时间分割
  • 日志分级
    • DEBUG:调试,等级最低,一般生产环境会将该等级的日志关闭
    • INFO:信息,普通等级,最常用的系统日志收集等级,一般会将系统运行中的一些相关信息(非开发类敏感信息)设为该等级
    • WARNFBI WARNNING大家都知道,就是警告,但又不到错误
    • ERROR:报错,一般程序报错使用该等级
    • FATAL:严重,比程序报错还严重的等级,如果没做错误等级划分的话,一般FATAL都不怎么用到,都用ERROR替代了
src/shared/logger.service.ts

import { Injectable, Scope } from '@nestjs/common';
import { createLogger, Logger, transports, format } from 'winston';

@Injectable({ scope: Scope.TRANSIENT })
export class AppLogger {
private context?: string;
private logger: Logger;

public setContext(context: string): void {
this.context = context;
}

constructor() {
this.logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp(),
format.prettyPrint(),
),

transports: [
new transports.Console(),
new transports.File({ filename: 'logs/error.log', level: 'error' }),
new transports.File({ filename: 'logs/combined.log' }),
],
});
}

error(
ctx: any,
message: string,
meta?: Record<string, any>,
): Logger {

return this.logger.error({
message,
contextName: this.context,
ctx,
...meta,
});
}

warn(
ctx: any,
message: string,
meta?: Record<string, any>,
): Logger {
return this.logger.warn({
message,
contextName: this.context,
ctx,
...meta,
});
}

debug(
ctx: any,
message: string,
meta?: Record<string, any>,
): Logger {

return this.logger.debug({
message,
contextName: this.context,
ctx,
...meta,
});
}

verbose(
ctx: any,
message: string,
meta?: Record<string, any>,
): Logger {
return this.logger.verbose({
message,
contextName: this.context,
ctx,
...meta,
});
}

log(
ctx: any,
message: string,
meta?: Record<string, any>,
): Logger {
return this.logger.info({
message,
contextName: this.context,
ctx,
...meta,
});
}
}


/src/shared/logger/logger.module.ts
import { Module } from '@nestjs/common';

import { AppLogger } from './logger.service';

@Module({
imports: [],
providers: [AppLogger],
exports: [AppLogger],
})
export class AppLoggerModule { }


src/shared/logger.service.ts
@Module({
imports: [
AppLoggerModule,
],
exports: [
AppLoggerModule,
],
})
export class SharedModule { }

测试

src/user/services/auth.services.ts
@Injectable()
export class AuthService {

constructor(
private readonly logger: AppLogger,
){
this.logger.setContext(AuthService.name);
}

/**
* 获取短信验证码
* @param mobile
*/
async login(dto: RegisterCodeDTO) {
this.logger.log(null, 'Login...')
}

}